GFileInfo *file_info,
GVariant *xattrs,
GInputStream **out_input,
+ guint64 *out_length,
GCancellable *cancellable,
GError **error)
{
ret = TRUE;
ot_transfer_out_value (out_input, &ret_input);
+ if (out_length)
+ *out_length = header_size + g_file_info_get_size (file_info);
out:
return ret;
}
gboolean
-ostree_content_file_parse (GFile *content_path,
- gboolean trusted,
- GInputStream **out_input,
- GFileInfo **out_file_info,
- GVariant **out_xattrs,
- GCancellable *cancellable,
- GError **error)
+ostree_content_stream_parse (GInputStream *input,
+ guint64 input_length,
+ gboolean trusted,
+ GInputStream **out_input,
+ GFileInfo **out_file_info,
+ GVariant **out_xattrs,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
- guint64 length;
guint32 archive_header_size;
guchar dummy[4];
gsize bytes_read;
ot_lvariant GVariant *file_header = NULL;
ot_lfree guchar *buf = NULL;
- ret_input = (GInputStream*)g_file_read (content_path, cancellable, error);
- if (!ret_input)
- goto out;
-
- content_file_info = g_file_input_stream_query_info ((GFileInputStream*)ret_input,
- OSTREE_GIO_FAST_QUERYINFO,
- cancellable, error);
- if (!content_file_info)
- goto out;
-
- length = g_file_info_get_size (content_file_info);
-
- if (!g_input_stream_read_all (ret_input,
+ if (!g_input_stream_read_all (input,
&archive_header_size, 4, &bytes_read,
cancellable, error))
goto out;
archive_header_size = GUINT32_FROM_BE (archive_header_size);
- if (archive_header_size > length)
+ if (archive_header_size > input_length)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"File header size %u exceeds size %" G_GUINT64_FORMAT,
- (guint)archive_header_size, length);
+ (guint)archive_header_size, input_length);
goto out;
}
/* Skip over padding */
- if (!g_input_stream_read_all (ret_input,
+ if (!g_input_stream_read_all (input,
dummy, 4, &bytes_read,
cancellable, error))
goto out;
buf = g_malloc (archive_header_size);
- if (!g_input_stream_read_all (ret_input, buf, archive_header_size, &bytes_read,
+ if (!g_input_stream_read_all (input, buf, archive_header_size, &bytes_read,
cancellable, error))
goto out;
file_header = g_variant_new_from_data (OSTREE_FILE_HEADER_GVARIANT_FORMAT,
error))
goto out;
if (ret_file_info)
- g_file_info_set_size (ret_file_info, length - archive_header_size - 8);
+ g_file_info_set_size (ret_file_info, input_length - archive_header_size - 8);
if (g_file_info_get_file_type (ret_file_info) != G_FILE_TYPE_REGULAR)
{
g_clear_object (&ret_input);
}
- /* Now give the input stream at its current position as return value */
+ ret = TRUE;
+ /* Give the input stream at its current position as return value;
+ * assuming the caller doesn't seek, this should be fine. We might
+ * want to wrap it though in a non-seekable stream.
+ **/
+ g_object_ref (input);
+ ot_transfer_out_value (out_input, &input);
+ ot_transfer_out_value (out_file_info, &ret_file_info);
+ ot_transfer_out_value (out_xattrs, &ret_xattrs);
+ out:
+ return ret;
+
+}
+
+gboolean
+ostree_content_file_parse (GFile *content_path,
+ gboolean trusted,
+ GInputStream **out_input,
+ GFileInfo **out_file_info,
+ GVariant **out_xattrs,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ guint64 length;
+ ot_lobj GInputStream *file_input = NULL;
+ ot_lobj GInputStream *ret_input = NULL;
+ ot_lobj GFileInfo *content_file_info = NULL;
+ ot_lobj GFileInfo *ret_file_info = NULL;
+ ot_lvariant GVariant *ret_xattrs = NULL;
+
+ file_input = (GInputStream*)g_file_read (content_path, cancellable, error);
+ if (!file_input)
+ goto out;
+
+ content_file_info = g_file_input_stream_query_info ((GFileInputStream*)file_input,
+ OSTREE_GIO_FAST_QUERYINFO,
+ cancellable, error);
+ if (!content_file_info)
+ goto out;
+
+ length = g_file_info_get_size (content_file_info);
+
+ if (!ostree_content_stream_parse (file_input, length, trusted,
+ out_input ? &ret_input : NULL,
+ &ret_file_info, &ret_xattrs,
+ cancellable, error))
+ goto out;
ret = TRUE;
ot_transfer_out_value (out_input, &ret_input);
return ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
}
-static gboolean
-stage_object_impl (OstreeRepo *self,
- OstreeObjectType objtype,
- gboolean store_if_packed,
- GInputStream *input,
- const char *expected_checksum,
- guchar **out_csum,
- GCancellable *cancellable,
- GError **error);
-
static gboolean
commit_loose_object_trusted (OstreeRepo *self,
const char *checksum,
return ret;
}
+typedef enum {
+ OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED = (1<<0),
+ OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID = (1<<1)
+} OstreeRepoStageFlags;
+
static gboolean
stage_object_impl (OstreeRepo *self,
+ OstreeRepoStageFlags flags,
OstreeObjectType objtype,
- gboolean store_if_packed,
GInputStream *input,
+ guint64 file_object_length,
const char *expected_checksum,
guchar **out_csum,
GCancellable *cancellable,
if (expected_checksum)
{
- if (!store_if_packed)
+ if (!(flags & OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED))
{
if (!repo_find_object (self, objtype, expected_checksum,
&stored_path, &pack_checksum, &pack_offset,
if (stored_path == NULL && pack_checksum == NULL)
{
ot_lvariant GVariant *file_header = NULL;
+ gboolean do_stage_bare_file;
if (out_csum)
{
checksum_input = ostree_checksum_input_stream_new (input, checksum);
}
- if (!ostree_create_temp_file_from_input (priv->tmp_dir,
- ostree_object_type_to_string (objtype), NULL,
- NULL, NULL,
- checksum_input ? (GInputStream*)checksum_input : input,
- &temp_file,
- cancellable, error))
- goto out;
+ do_stage_bare_file = (flags & OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID)
+ && objtype == OSTREE_OBJECT_TYPE_FILE
+ && priv->mode == OSTREE_REPO_MODE_BARE;
+ if (do_stage_bare_file)
+ {
+ ot_lobj GInputStream *file_input = NULL;
+ ot_lobj GFileInfo *file_info = NULL;
+ ot_lvariant GVariant *xattrs = NULL;
+ if (!ostree_content_stream_parse (checksum_input ? (GInputStream*)checksum_input : input,
+ file_object_length, FALSE,
+ &file_input, &file_info, &xattrs,
+ cancellable, error))
+ goto out;
+
+ if (!ostree_create_temp_file_from_input (priv->tmp_dir,
+ ostree_object_type_to_string (objtype), NULL,
+ file_info, xattrs, file_input,
+ &temp_file,
+ cancellable, error))
+ goto out;
+ }
+ else
+ {
+ if (!ostree_create_temp_file_from_input (priv->tmp_dir,
+ ostree_object_type_to_string (objtype), NULL,
+ NULL, NULL,
+ checksum_input ? (GInputStream*)checksum_input : input,
+ &temp_file,
+ cancellable, error))
+ goto out;
+ }
+
if (!checksum)
actual_checksum = expected_checksum;
else
}
- if (!store_if_packed)
+ if (!(flags & OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED))
{
gboolean have_obj;
if (do_commit)
{
- if (objtype == OSTREE_OBJECT_TYPE_FILE && priv->mode == OSTREE_REPO_MODE_BARE)
+ /* Only do this if we *didn't* stage a bare file above */
+ if (!do_stage_bare_file
+ && objtype == OSTREE_OBJECT_TYPE_FILE && priv->mode == OSTREE_REPO_MODE_BARE)
{
ot_lobj GInputStream *file_input = NULL;
ot_lobj GFileInfo *file_info = NULL;
GError **error)
{
gboolean ret = FALSE;
- ot_lobj GInputStream *mem = NULL;
+ ot_lobj GInputStream *input = NULL;
- mem = g_memory_input_stream_new_from_data (g_variant_get_data (variant),
- g_variant_get_size (variant),
- NULL);
+ input = ot_variant_read (variant);
- if (!stage_object_impl (self, type, FALSE, mem,
- NULL, out_csum, cancellable, error))
+ if (!stage_object_impl (self, 0, type, input, 0, NULL,
+ out_csum, cancellable, error))
goto out;
ret = TRUE;
GCancellable *cancellable,
GError **error)
{
- return stage_object_impl (self, objtype, store_if_packed,
- object_input, checksum, NULL,
+ int flags = 0;
+ if (store_if_packed)
+ flags |= OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED;
+ return stage_object_impl (self, flags, objtype,
+ object_input, 0, checksum, NULL,
cancellable, error);
}
gboolean ret = FALSE;
ot_lfree guchar *actual_csum = NULL;
- if (!stage_object_impl (self, objtype, FALSE,
- object_input, expected_checksum, &actual_csum,
+ if (!stage_object_impl (self, 0, objtype,
+ object_input, 0, expected_checksum, &actual_csum,
+ cancellable, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
+ostree_repo_stage_file_object_trusted (OstreeRepo *self,
+ const char *checksum,
+ gboolean store_if_packed,
+ GInputStream *object_input,
+ guint64 length,
+ GCancellable *cancellable,
+ GError **error)
+{
+ int flags = OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID;
+ if (store_if_packed)
+ flags |= OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED;
+ return stage_object_impl (self, flags, OSTREE_OBJECT_TYPE_FILE,
+ object_input, length, checksum, NULL,
+ cancellable, error);
+}
+
+gboolean
+ostree_repo_stage_file_object (OstreeRepo *self,
+ const char *expected_checksum,
+ GInputStream *object_input,
+ guint64 length,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ int flags = OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID;
+ ot_lfree guchar *actual_csum = NULL;
+
+ if (!stage_object_impl (self, flags, OSTREE_OBJECT_TYPE_FILE,
+ object_input, length, expected_checksum, &actual_csum,
cancellable, error))
goto out;
else
{
ot_lobj GInputStream *file_object_input = NULL;
+ guint64 file_obj_length;
g_clear_object (&file_input);
if (g_file_info_get_file_type (modified_info) == G_FILE_TYPE_REGULAR)
g_free (child_file_csum);
child_file_csum = NULL;
- if (!ostree_raw_file_to_content_stream (file_input, modified_info, xattrs,
- &file_object_input, cancellable, error))
+ if (!ostree_raw_file_to_content_stream (file_input,
+ modified_info, xattrs,
+ &file_object_input, &file_obj_length,
+ cancellable, error))
goto out;
- if (!stage_object_impl (self, OSTREE_OBJECT_TYPE_FILE, FALSE,
- file_object_input, NULL,
- &child_file_csum, cancellable, error))
+ if (!stage_object_impl (self, OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID,
+ OSTREE_OBJECT_TYPE_FILE, file_object_input, file_obj_length,
+ NULL, &child_file_csum, cancellable, error))
goto out;
g_free (tmp_checksum);
gboolean ret = FALSE;
ot_lobj GInputStream *file_object_input = NULL;
ot_lobj GInputStream *archive_stream = NULL;
+ guint64 length;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
archive_stream = ostree_libarchive_input_stream_new (a);
if (!ostree_raw_file_to_content_stream (archive_stream, file_info, NULL,
- &file_object_input, cancellable, error))
+ &file_object_input, &length, cancellable, error))
goto out;
- if (!stage_object_impl (self, OSTREE_OBJECT_TYPE_FILE, FALSE,
- file_object_input, NULL, out_csum,
+ if (!stage_object_impl (self, OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID, OSTREE_OBJECT_TYPE_FILE,
+ file_object_input, length, NULL, out_csum,
cancellable, error))
goto out;